// internal/parser/ast/statement.go
package ast

import (
	"fmt"
	"strings"
)

// SelectStatement 表示SELECT查询语句
type SelectStatement struct {
	Columns     []Expression        // 选择的列列表，如 id, name
	TableName   string              // 查询的表名，如 users
	TableAlias  string              // 表别名，如 u
	Subquery    *SubqueryExpression // FROM子句中的子查询
	JoinClauses []JoinClause        // JOIN子句列表
	Where       Expression          // WHERE条件，如 age > 18
	OrderBy     []OrderByClause     // ORDER BY子句列表
	Limit       *LimitClause        // LIMIT子句
}

// 实现Statement接口
func (s *SelectStatement) statementNode()       {}
func (s *SelectStatement) TokenLiteral() string { return "SELECT" }
func (s *SelectStatement) String() string {
	// 实现String方法，生成SQL语句的字符串表示
	var out strings.Builder

	out.WriteString("SELECT ")

	for i, col := range s.Columns {
		if i > 0 {
			out.WriteString(", ")
		}
		out.WriteString(col.String())
	}

	out.WriteString(" FROM ")

	// 根据是使用表名还是子查询来生成FROM子句
	if s.Subquery != nil {
		out.WriteString(s.Subquery.String())
	} else {
		out.WriteString(s.TableName)
	}

	if s.TableAlias != "" {
		out.WriteString(" ")
		out.WriteString(s.TableAlias)
	}

	// 添加 JOIN 子句
	for _, join := range s.JoinClauses {
		out.WriteString(" ")
		switch join.JoinType {
		case INNER:
			out.WriteString("INNER JOIN")
		case LEFT:
			out.WriteString("LEFT JOIN")
		case RIGHT:
			out.WriteString("RIGHT JOIN")
		case FULL:
			out.WriteString("FULL JOIN")
		}
		out.WriteString(" ")
		out.WriteString(join.TableName)
		if join.Alias != "" {
			out.WriteString(" ")
			out.WriteString(join.Alias)
		}
		out.WriteString(" ON ")
		out.WriteString(join.Condition.LeftTable)
		out.WriteString(".")
		out.WriteString(join.Condition.LeftColumn)
		out.WriteString(" = ")
		out.WriteString(join.Condition.RightTable)
		out.WriteString(".")
		out.WriteString(join.Condition.RightColumn)
	}

	if s.Where != nil {
		out.WriteString(" WHERE ")
		out.WriteString(s.Where.String())
	}

	// 生成ORDER BY子句
	if len(s.OrderBy) > 0 {
		out.WriteString(" ORDER BY ")
		for i, order := range s.OrderBy {
			if i > 0 {
				out.WriteString(", ")
			}
			out.WriteString(order.String())
		}
	}

	// 生成LIMIT子句
	if s.Limit != nil {
		out.WriteString(" LIMIT ")
		out.WriteString(s.Limit.String())
	}

	return out.String()
}

// CreateTableStatement 表示CREATE TABLE语句
type CreateTableStatement struct {
	TableName string             // 要创建的表名
	Columns   []ColumnDefinition // 列定义列表
}

// 实现Statement接口
func (c *CreateTableStatement) statementNode()       {}
func (c *CreateTableStatement) TokenLiteral() string { return "CREATE TABLE" }
func (c *CreateTableStatement) String() string {
	var out strings.Builder

	out.WriteString("CREATE TABLE ")
	out.WriteString(c.TableName)
	out.WriteString(" (")

	for i, col := range c.Columns {
		if i > 0 {
			out.WriteString(", ")
		}
		out.WriteString(col.String())
	}

	out.WriteString(")")
	return out.String()
}

// ColumnDefinition 表示表中的列定义
type ColumnDefinition struct {
	Name       string // 列名
	Type       string // 数据类型，如INT, VARCHAR等
	NotNull    bool   // 是否有NOT NULL约束
	PrimaryKey bool   // 是否是主键
}

func (c *ColumnDefinition) String() string {
	var out strings.Builder

	out.WriteString(c.Name)
	out.WriteString(" ")
	out.WriteString(c.Type)

	if c.NotNull {
		out.WriteString(" NOT NULL")
	}

	if c.PrimaryKey {
		out.WriteString(" PRIMARY KEY")
	}

	return out.String()
}

// InsertStatement 表示INSERT语句
type InsertStatement struct {
	TableName string       // 要插入数据的表名
	Columns   []string     // 列名列表
	Values    []Expression // 值列表
}

// 实现Statement接口
func (i *InsertStatement) statementNode()       {}
func (i *InsertStatement) TokenLiteral() string { return "INSERT" }
func (i *InsertStatement) String() string {
	var out strings.Builder

	out.WriteString("INSERT INTO ")
	out.WriteString(i.TableName)

	if len(i.Columns) > 0 {
		out.WriteString(" (")
		out.WriteString(strings.Join(i.Columns, ", "))
		out.WriteString(")")
	}

	out.WriteString(" VALUES (")

	for i, val := range i.Values {
		if i > 0 {
			out.WriteString(", ")
		}
		out.WriteString(val.String())
	}

	out.WriteString(")")
	return out.String()
}

// UpdateStatement 表示UPDATE语句
type UpdateStatement struct {
	TableName string                // 要更新的表名
	Updates   map[string]Expression // 列名到新值的映射
	Where     Expression            // WHERE条件
}

// 实现Statement接口
func (u *UpdateStatement) statementNode()       {}
func (u *UpdateStatement) TokenLiteral() string { return "UPDATE" }
func (u *UpdateStatement) String() string {
	var out strings.Builder

	out.WriteString("UPDATE ")
	out.WriteString(u.TableName)
	out.WriteString(" SET ")

	i := 0
	for col, val := range u.Updates {
		if i > 0 {
			out.WriteString(", ")
		}
		out.WriteString(col)
		out.WriteString(" = ")
		out.WriteString(val.String())
		i++
	}

	if u.Where != nil {
		out.WriteString(" WHERE ")
		out.WriteString(u.Where.String())
	}

	return out.String()
}

// DropStatement 表示DROP语句
type DropStatement struct {
	ObjectType string // 对象类型，如 "TABLE"
	Name       string // 要删除的对象名称
}

// 实现Statement接口
func (d *DropStatement) statementNode()       {}
func (d *DropStatement) TokenLiteral() string { return "DROP" }
func (d *DropStatement) String() string {
	return fmt.Sprintf("DROP %s %s", d.ObjectType, d.Name)
}

// JoinType 表示连接类型
type JoinType int

const (
	INNER JoinType = iota
	LEFT
	RIGHT
	FULL
)

// JoinCondition 表示JOIN条件
type JoinCondition struct {
	LeftTable   string
	LeftColumn  string
	RightTable  string
	RightColumn string
}

// JoinClause 表示JOIN子句
type JoinClause struct {
	JoinType  JoinType
	TableName string
	Alias     string
	Condition JoinCondition
}

// DeleteStatement 表示DELETE语句
type DeleteStatement struct {
	TableName string     // 要删除数据的表名
	Where     Expression // WHERE条件，如 id = 1
}

// 实现Statement接口
func (d *DeleteStatement) statementNode()       {}
func (d *DeleteStatement) TokenLiteral() string { return "DELETE" }
func (d *DeleteStatement) String() string {
	var out strings.Builder

	out.WriteString("DELETE FROM ")
	out.WriteString(d.TableName)

	if d.Where != nil {
		out.WriteString(" WHERE ")
		out.WriteString(d.Where.String())
	}

	return out.String()
}

// AlterActionType 表示ALTER TABLE操作的类型
type AlterActionType int

const (
	AddColumn AlterActionType = iota
	ModifyColumn
	ChangeColumn
	DropColumn
	AddConstraint
	DropConstraint
)

// ColumnComment 表示列的注释
type ColumnComment struct {
	Text string
}

// ColumnDefault 表示列的默认值
type ColumnDefault struct {
	Value Expression
}

// ConstraintType 表示约束类型
type ConstraintType int

const (
	UniqueConstraint ConstraintType = iota
	PrimaryKeyConstraint
	ForeignKeyConstraint
	CheckConstraint
)

// Constraint 表示表的约束
type Constraint struct {
	Name            string         // 约束名称
	Type            ConstraintType // 约束类型
	Columns         []string       // 约束涉及的列
	ReferencedTable string         // 被引用的表（外键约束）
	ReferencedCols  []string       // 被引用的列（外键约束）
	CheckExpr       Expression     // 检查约束的表达式
}

// 返回约束的字符串表示
func (c *Constraint) String() string {
	var out strings.Builder

	if c.Name != "" {
		out.WriteString("CONSTRAINT ")
		out.WriteString(c.Name)
		out.WriteString(" ")
	}

	switch c.Type {
	case UniqueConstraint:
		out.WriteString("UNIQUE (")
		out.WriteString(strings.Join(c.Columns, ", "))
		out.WriteString(")")
	case PrimaryKeyConstraint:
		out.WriteString("PRIMARY KEY (")
		out.WriteString(strings.Join(c.Columns, ", "))
		out.WriteString(")")
	case ForeignKeyConstraint:
		out.WriteString("FOREIGN KEY (")
		out.WriteString(strings.Join(c.Columns, ", "))
		out.WriteString(") REFERENCES ")
		out.WriteString(c.ReferencedTable)
		out.WriteString(" (")
		out.WriteString(strings.Join(c.ReferencedCols, ", "))
		out.WriteString(")")
	case CheckConstraint:
		out.WriteString("CHECK (")
		if c.CheckExpr != nil {
			out.WriteString(c.CheckExpr.String())
		}
		out.WriteString(")")
	}

	return out.String()
}

// AlterColumnDef 表示修改列的定义
type AlterColumnDef struct {
	OldName string         // 修改前的列名（用于CHANGE语句）
	Name    string         // 列名
	Type    string         // 数据类型
	NotNull bool           // 是否有NOT NULL约束
	Default *ColumnDefault // 默认值
	Comment *ColumnComment // 列注释
}

// AlterAction 表示一个ALTER TABLE操作
type AlterAction struct {
	Type           AlterActionType // 操作类型
	ColumnDef      *AlterColumnDef // 列定义（用于ADD/MODIFY/CHANGE）
	ColumnName     string          // 列名（用于DROP COLUMN）
	Constraint     *Constraint     // 约束定义（用于ADD CONSTRAINT）
	ConstraintName string          // 约束名（用于DROP CONSTRAINT）
}

// AlterTableStatement 表示ALTER TABLE语句
type AlterTableStatement struct {
	TableName string        // 要修改的表名
	Actions   []AlterAction // 要执行的操作列表
}

// 实现Statement接口
func (a *AlterTableStatement) statementNode()       {}
func (a *AlterTableStatement) TokenLiteral() string { return "ALTER TABLE" }
func (a *AlterTableStatement) String() string {
	var out strings.Builder

	out.WriteString("ALTER TABLE ")
	out.WriteString(a.TableName)
	out.WriteString(" ")

	for i, action := range a.Actions {
		if i > 0 {
			out.WriteString(", ")
		}

		switch action.Type {
		case AddColumn:
			out.WriteString("ADD COLUMN ")
			out.WriteString(action.ColumnDef.Name)
			out.WriteString(" ")
			out.WriteString(action.ColumnDef.Type)

			if action.ColumnDef.NotNull {
				out.WriteString(" NOT NULL")
			}

			if action.ColumnDef.Default != nil {
				out.WriteString(" DEFAULT ")
				out.WriteString(action.ColumnDef.Default.Value.String())
			}

			if action.ColumnDef.Comment != nil {
				out.WriteString(" COMMENT '")
				out.WriteString(action.ColumnDef.Comment.Text)
				out.WriteString("'")
			}

		case ModifyColumn:
			out.WriteString("MODIFY COLUMN ")
			out.WriteString(action.ColumnDef.Name)
			out.WriteString(" ")
			out.WriteString(action.ColumnDef.Type)

			if action.ColumnDef.NotNull {
				out.WriteString(" NOT NULL")
			}

			if action.ColumnDef.Default != nil {
				out.WriteString(" DEFAULT ")
				out.WriteString(action.ColumnDef.Default.Value.String())
			}

			if action.ColumnDef.Comment != nil {
				out.WriteString(" COMMENT '")
				out.WriteString(action.ColumnDef.Comment.Text)
				out.WriteString("'")
			}

		case ChangeColumn:
			out.WriteString("CHANGE COLUMN ")
			out.WriteString(action.ColumnDef.OldName)
			out.WriteString(" ")
			out.WriteString(action.ColumnDef.Name)
			out.WriteString(" ")
			out.WriteString(action.ColumnDef.Type)

			if action.ColumnDef.NotNull {
				out.WriteString(" NOT NULL")
			}

			if action.ColumnDef.Default != nil {
				out.WriteString(" DEFAULT ")
				out.WriteString(action.ColumnDef.Default.Value.String())
			}

			if action.ColumnDef.Comment != nil {
				out.WriteString(" COMMENT '")
				out.WriteString(action.ColumnDef.Comment.Text)
				out.WriteString("'")
			}

		case DropColumn:
			out.WriteString("DROP COLUMN ")
			out.WriteString(action.ColumnName)

		case AddConstraint:
			out.WriteString("ADD ")
			out.WriteString(action.Constraint.String())

		case DropConstraint:
			out.WriteString("DROP CONSTRAINT ")
			out.WriteString(action.ConstraintName)
		}
	}

	return out.String()
}
